package com.hitqz.robot.biz.flow.component.gf;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hitqz.robot.api.business.entity.PatrolResultEntity;
import com.hitqz.robot.api.business.enums.ResultTypeEnum;
import com.hitqz.robot.api.business.model.dto.FlowContextDto;
import com.hitqz.robot.api.business.model.dto.FlowPatrolPreAndEndTicketsDto;
import com.hitqz.robot.api.common.entity.*;
import com.hitqz.robot.biz.core.FileProperties;
import com.hitqz.robot.biz.service.*;
import com.hitqz.robot.camera.EquipmentFactory;
import com.hitqz.robot.driver.model.IRobotPosDto;
import com.hitqz.robot.driver.parent.RobotDriverService;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.core.NodeComponent;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.web.ServerProperties;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URL;
import java.util.*;
import java.util.concurrent.ExecutorService;

/**
 * @author xupkun
 * @date 2024/10/14
 */
@Slf4j
@LiteflowComponent(value = "WriteGfResultComponent", name = "[光伏机器人]写入结果")
@RequiredArgsConstructor
public class WriteGfResultComponent extends NodeComponent {

    private final RobotMapPosService robotMapPosService;

    private final RobotDriverService robotDriverService;

    private final ExecutorService customThreadPool;

    private final ServerProperties serverProperties;

    private final RobotEquipmentService robotEquipmentService;

    private final EquipmentFactory equipmentFactory;

    private final PatrolCheckTypeService patrolCheckTypeService;

    private final RobotService robotService;

    private final FileProperties fileProperties;

    private final PatrolItemService patrolItemService;

    private final PatrolObjectService patrolObjectService;

    private final PatrolResultService patrolResultService;

    private final PatrolObjectStandardService patrolObjectStandardService;

    private Robot robot;

    private Integer ticketsId;

    @Override
    public void process() throws Exception {
        FlowContextDto dto = this.getRequestData();
        ticketsId = dto.getTickets().getId().intValue();
        FlowPatrolPreAndEndTicketsDto ticketsDto = JSONObject.parseObject(dto.getTicketsTask().getParseOrderParams(), FlowPatrolPreAndEndTicketsDto.class);
        Map<String, Object> modalData = ticketsDto.getModalData();
        if (!modalData.containsKey("isDetect")){
            return;
        }
        robot = robotService.getDefaultRobot();
        boolean isDetect =Boolean.valueOf((String)modalData.get("isDetect"));
        if (isDetect){
            //进行检测
            List<RobotMapPos> list = robotMapPosService.list();
            if (list.isEmpty()){
                return;
            }
            list =  list.stream().sorted(Comparator.comparing(RobotMapPos::getPosX)).toList();
            for (RobotMapPos robotMapPos : list) {
                for (int i = 0; i < 100; i++) {
                    IRobotPosDto webPos = robotDriverService.getWebPos();
                    Thread.sleep(100);
                    if (Math.abs(robotMapPos.getPosX()-webPos.getX())<3000){
                        this.detect(robotMapPos);
                        log.info("到达点位{}检测",robotMapPos.getName());
                        break;
                    }
                    if (robotMapPos.getPosX()<webPos.getX()){
                        log.info("走超过了，丢弃");
                        break;
                    }
                }
            }
        }
    }


    private void detect(RobotMapPos robotMapPos){
        List<PatrolCheckType> list = patrolCheckTypeService.list();
        if (list.isEmpty()){
            log.info("没有检测项类型");
            return;
        }
        for (PatrolCheckType patrolCheckType : list) {
            //发送给视觉
            String visionUrl = patrolCheckType.getVisionUrl();
            String type = patrolCheckType.getVisionType();
            HashMap<String, Object> query = new HashMap<>();
            query.put("rectype",Integer.parseInt(type));
            log.info("视觉地址：{},参数:{}",visionUrl,JSONObject.toJSONString(query));
            String reply = HttpUtil.post(visionUrl, JSONObject.toJSONString(query), 5000);
            log.info("视觉检测结果: {}", reply);
            String result = "";
            if (StrUtil.isNotBlank(reply)){
                JSONObject jsonObject = JSONObject.parseObject(reply);
                Integer code = jsonObject.getInteger("code");
                if (Objects.equals(code, 200)) {
                    if (StrUtil.isNotBlank(jsonObject.getString("result"))) {
                        result = jsonObject.getString("result").replace("a","").replace("b","").replace("c","");
                    }
                    //写记录
                    String[] results = result.replace("[","").replace("]","").split(",");
                    for (int i = 0; i < results.length; i++) {
                        String visionPath = "";
                        if (StrUtil.isNotBlank(jsonObject.getString("path"))) {
                            String[] paths = jsonObject.getString("path").split(",");
                            String downLoadPath = downloadImage(paths[Math.min(paths.length-1,i)]);
                            if (StrUtil.isNotBlank(downLoadPath)){
                                visionPath = downLoadPath;
                            }
                        }
                        writeResult(robotMapPos,patrolCheckType,visionPath,results[i]);
                    }
                }
            }
        }

    }

    private void writeResult(RobotMapPos robotMapPos,PatrolCheckType patrolCheckType,String visionPath,String result){
        PatrolObject patrolObject = patrolObjectService.getOne(Wrappers.<PatrolObject>lambdaQuery().eq(PatrolObject::getPatrolCheckTypeId, patrolCheckType.getId()).last("limit 1"));
        PatrolObjectStandard standard = patrolObjectStandardService.getOne(Wrappers.<PatrolObjectStandard>lambdaQuery().eq(PatrolObjectStandard::getPatrolObjectId, patrolObject.getId()).last("limit 1"));
        PatrolResultEntity patrolResult = new PatrolResultEntity();
        patrolResult.setCreateTime(new Date());
        patrolResult.setTicketsId(ticketsId);
        patrolResult.setDevName(robotMapPos.getName());
        patrolResult.setItemId(0);
        patrolResult.setItemName(patrolObject.getName());
        patrolResult.setCheckTime(new Date());
        //处理结果数据
        patrolResult.setVisionResult(result);
        patrolResult.setConvertValue(result);
        if (Objects.equals(patrolObject.getIsConvert(), 1) && StrUtil.isNotBlank(result)) {
            // 转换后的值,用来比较和做数据统计的
            // 0-无返回 1-浮点型 2-单个枚举 3-多个枚举 4-字符串 5-数显
            String resultType = patrolCheckType.getResultType();
            ResultTypeEnum resultTypeEnum = ResultTypeEnum.fromType(resultType);
            if (resultTypeEnum != null) {
                switch (resultTypeEnum) {
                    //todo 新增和编辑去检查有没有 ,
                    case FLOAT -> {
                        String[] convertValues = patrolObject.getFloatConvert().split(",");
                        BigDecimal convertMinValue = new BigDecimal(convertValues[0]);
                        BigDecimal convertMaxValue = new BigDecimal(convertValues[1]);
                        BigDecimal visionResult = new BigDecimal(result);
                        double convertValue = visionResult.multiply(convertMaxValue.subtract(convertMinValue)).add(convertMinValue).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                        patrolResult.setConvertValue(String.valueOf(convertValue));
                    }
                    case SINGLE_ENUM, MULTI_ENUM -> {
                        String[] enumResults = patrolObject.getEnumResult().split(",");
                        String[] enumConverts = patrolObject.getEnumConvert().split(",");
                        StringBuilder convertValue = new StringBuilder(result);
                        for (int i = 0; i < enumResults.length; i++) {
                            if (StrUtil.isNotBlank(result) && result.contains(enumResults[i])) {
                                convertValue.append(enumConverts[i]).append(" ");
                            }
                        }
                        patrolResult.setConvertValue(convertValue.toString().trim());
                    }
                    case LED -> {
                        Integer afterPointCountConvert = patrolObject.getAfterPointCountConvert();
                        if (!result.contains(".") && Objects.equals(afterPointCountConvert,0)) {
                            BigDecimal value = new BigDecimal(result);
                            BigDecimal point = BigDecimal.valueOf(Math.pow(10, afterPointCountConvert));
                            double v = value.divide(point).setScale(afterPointCountConvert, BigDecimal.ROUND_HALF_UP).doubleValue();
                            patrolResult.setConvertValue(String.valueOf(v));
                        }
                    }
                }
            }
        }
        // 对比结果
        // 0-未检测 1-正常 2-异常 3-视觉识别失败
        patrolResult.setStatus(1);
        String normalValue = Optional.ofNullable(standard).map(PatrolObjectStandard::getStandardValue).orElse("");
        if (Objects.equals(patrolCheckType.getIsVision(), 1) && StrUtil.isBlank(result)) {
            //视觉检测项但是没有结果，判定为失败
            patrolResult.setStatus(3);
        } else if (StrUtil.isNotBlank(normalValue) && StrUtil.isNotBlank(patrolResult.getConvertValue())) {
            switch (Optional.ofNullable(standard).map(PatrolObjectStandard::getType).orElse("-1")) {
                case "1" -> {
                    //值判定
                    patrolResult.setStatus(normalValue.contains(patrolResult.getConvertValue()) ? 1 : 2);
                }
                case "2" -> {
                    //区间判定 todo 新增和编辑去检查有没有 ,
                    String[] values = normalValue.split(",");
                    float minValue = Float.parseFloat(values[0]);
                    float maxValue = Float.parseFloat(values[1]);
                    float checkValue = Float.parseFloat(patrolResult.getConvertValue());
                    patrolResult.setStatus((minValue <= checkValue && checkValue <= maxValue) ? 1 : 2);
                }
            }
        }
        // 标准值
        patrolResult.setNormalValue(normalValue);
        // 展示在报表的值 转换后的值+单位
        patrolResult.setShowValue(Optional.ofNullable(patrolResult.getConvertValue()).orElse("") + " " + patrolObject.getUnit());
        patrolResult.setMediaUrl(visionPath);
        patrolResult.setVisionMediaUrl(visionPath);
        patrolResultService.saveOrUpdate(patrolResult);


    }


    /**
     * 下载图片到本地
     * @param imageUrl 视觉 url
     * @return url 本地的相对路径
     */
    private String downloadImage(String imageUrl) {
        InputStream in = null;
        String relativePath =  File.separator + "vision_draw" + File.separator + DateUtil.format(new Date(),"yyyyMMdd") + File.separator + DateUtil.format(new Date(),"yyyyMMddHHmmssSSS") + ".jpg";
        String path = fileProperties.getLocal().getBasePath() + relativePath;
        try  {  // 打开输入流
            URL url = new URL(imageUrl.replace("/./","/"));  // 创建 URL 对象
            in = url.openStream();
            FileUtil.writeFromStream(in,path);
            return relativePath;
        } catch (IOException e) {
            log.error("down vision picture error:{}",e.getMessage());
            return "";
        } finally {
            try {
                if (in!=null) {
                    in.close();
                }
            } catch (IOException e) {
                log.error("InputStream close error:{}",e.getMessage());
            }
        }
    }


}
